#include "server.h"
#define BUFSIZE 1024
 
void initserver()
{
    //将STDIN_FILENO修改为非阻塞
    int ops,stdinflags;
    if((ops=fcntl(STDIN_FILENO,F_GETFL,0))<0)
    {
        printf("get stdin error\n");
        exit(0);
    }
    if((stdinflags=fcntl(STDIN_FILENO,F_SETFL,ops|O_NONBLOCK))<0)
    {
        printf("set stdin error\n");
        exit(0);
    }
    //以非阻塞只读的方式打开管道
    if((publicfifo=open(PUBLICFIFO,O_RDONLY|O_NONBLOCK))<0)
    {
        perror("publicfifo open\n");
        exit(1);
    }
    printf("The server has been started and is listening...\n");
    startflags=1-startflags; //服务器已经启动
}
 
void receiverpacket()
{
    char buf[BUFSIZE];
    MSP *msp;
    int len;
    if((len=read(publicfifo,buf,sizeof(buf)))>0)
    {
        msp=(MSP*)buf;
        parsingpacket(msp);
    }
}
 
void parsingpacket(MSP *msp)
{
    //根据相应的功能号，调用相应的函数。
    switch(msp->messageNo)
    {
        case 0:
            clientlogin(msp->senderName);
            break;
        case 1:
            messagesend(msp);
            break;
        case 2:
            clientquit(msp->senderName);
            break;
    }
}
 
void clientlogin(char* loginName)
{
    //不能直接赋值，会造成浅拷贝
    strcpy(clientQueue[clientlen].clientName,loginName);
    char path[23]="./";
    strcat(path,loginName);
    umask(0);
    mkfifo(path,0777);
    //将管道的文件描述符存入数组中
    clientQueue[clientlen].privatefifo=open(path,O_WRONLY);
    char buf[]="Your connection with the server has been successfully established and you can start communication\n";
    write(clientQueue[clientlen].privatefifo,buf,sizeof(buf));
    //这里应该将管道创建为临时的，如果是使用数据库，可以创建为永久的
    unlink(path);  //只有当另外的进程关闭该path文件的时候才删除path
    ++clientlen;
}
 
void clientquit(char* quitName)
{
    int i=0;
    //查找存储客户端结构体中名字为quitName的客户端，并删除
    for(i=0;i<clientlen;i++)
    {
        if(strcmp(quitName,clientQueue[i].clientName)==0)
            {
                //关闭对应的私有通道
                close(clientQueue[i].privatefifo);
                clientQueue[i].privatefifo=-1;
                clientQueue[i].clientName[0]='\0';
                break;
            }
    }
    printf("%s already quit\n",quitName);
}
 
void messagesend(MSP *pMes)
{
    int i=0;
    char* buf=(void*)pMes;
    if(strlen(pMes->receiverName)!=0)
    {
        //单发
        for(i=0;i<clientlen;++i)
        {
            if(strcmp(pMes->receiverName,clientQueue[i].clientName)==0)
            {
                write(clientQueue[i].privatefifo,buf,BUFSIZE);
                break;
            }
        }
    }
    else
    {
        //群发
        for(i=0;i<clientlen;++i)
        {
            write(clientQueue[i].privatefifo,buf,BUFSIZE);
        }
    }
}
 
void messagehanle(char* pMes)
{
    if(strcmp(pMes,"quit")==0||strcmp(pMes,"exit")==0) 
    {
        closeserver();
    }
}
void closeserver()
{
    char buf[]="Server maintenance, please log in later.\n";
    int i=0;
    //把服务器关闭的信息发送给各个打开着的客户端，然后关闭
    for(i=0;i<clientlen;++i)
    {
        if(clientQueue[i].privatefifo!=-1)
        {
            write(clientQueue[i].privatefifo,buf,strlen(buf));
            close(clientQueue[i].privatefifo);
        }
    }
    close(publicfifo);
    startflags=1-startflags;  //服务器已经关闭
    printf("All pipes have been closed and the server exited safely\n");
}
int main()
{
    initserver();
    char mes[1024];
    while(startflags)
    {
        receiverpacket();
        if(scanf("%s",mes)!=EOF)
        {
            messagehanle(mes);
        }
    }
    return 0;
}